package growth.net.peer;

import growth.net.utils.Utils;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class Peer {

    public static String peerName = null;
    public static InetAddress ip = null;
    public static ArrayList<Node> neighboursList = new ArrayList<>();
    public static ArrayList<Message> messageList = new ArrayList<>();
    public static InetAddress REGISTER_IP = null;
    public static int REGISTER_PORT = 3000;
    public static ListeningService listeningService = null;
    public static SendingService sendingService = null;
    public static String SCRIPT = "/opt/growthnet/node_script.sh";

    public static void main(String[] args) {
        Peer peer = new Peer();
        peer.createNode(Integer.parseInt(args[0]));
    }

    public void createNode(int PORT) {
        RequestProcessor reqeustProcess = null;
        Peer.peerName = Utils.getUniqueId();
        try {
            REGISTER_IP = InetAddress.getLocalHost();
            Peer.ip = InetAddress.getLocalHost();
            listeningService = new ListeningService();
            Thread listenServiceThread = new Thread(listeningService);
            listenServiceThread.start();
            sendingService = SendingService.getSendingService();
            reqeustProcess = new RequestProcessor();
            reqeustProcess.registerToGrowthNet(peerName, ListeningService.portNum,
                    sendingService.sendingPort, InetAddress.getLocalHost(),
                    PORT, InetAddress.getLocalHost());

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        boolean hasToRun = true;
        while (hasToRun) {
            String option = null;
            Utils.showMenu(peerName);
            option = Utils.readValueFromCommmandLine();
            try {
                int choice = Integer.parseInt(option);
                switch (choice) {
                    case 0:
                        System.out.println("------------------------");
                        System.out.println("Node Name: " + peerName);
                        System.out.println("------------------------");
                        break;
                    case 1:
                        String[] params = {SCRIPT, "" + ListeningService.portNum};
                        Runtime.getRuntime().exec(params);
                        break;
                    case 2:
                        Utils.showLeaveSubMenu();
                        int pick = Utils.getInteger();
                        if (pick == 0) {
                            reqeustProcess.sendLinkAllDeleteMeMessage(REGISTER_PORT, REGISTER_IP);
                        } else if (pick == 1) {
                            reqeustProcess.sendCircularLinkDeleteMeMessage(REGISTER_PORT, REGISTER_IP);
                        } else {
                            System.out.println("invalid choice!! Leave aborted");
                            break;
                        }
                        listeningService.stopListening();
                        reqeustProcess.sendDeleteMeFromGraph(REGISTER_PORT, REGISTER_IP);
                        System.out.println(" Leaving the network, Bye Bye !!");
//                        System.exit(0);
                        hasToRun = false;
                        break;
                    case 3:
                        System.out.print("\nNeighbor Nodes: \n");
                        for (Node nbr : Peer.neighboursList) {
                            System.out.println(nbr.name + " ");
                        }
                        System.out.println("-------------------------");
                        break;

                    case 4:
                        Message message = new Message();
                        System.out.print("Enter the message: ");
                        message.body = Utils.readValueFromCommmandLine();
                        message.id = Utils.getUniqueId();
                        message.timeToLive = Message.INFINITE;
                        message.sourceid = Peer.peerName;
                        Peer.messageList.add(message);
                        reqeustProcess.sendBroadcastMessage(message);
                        break;

                    case 5:
                        System.out.println("Enter the details of the node to add");
                        Node newnbr = new Node();
                        System.out.println("Name:");
                        newnbr.name = Utils.readValueFromCommmandLine();

                        System.out.println("Listening port:");
                        newnbr.listPort = Integer.parseInt(Utils.readValueFromCommmandLine().trim());
                        System.out.println("Send port");
                        newnbr.sendPort = Integer.parseInt(Utils.readValueFromCommmandLine().trim());
                        System.out.println("HOST");
                        newnbr.ip = InetAddress.getByName(Utils.readValueFromCommmandLine().trim());
                        Peer.neighboursList.add(newnbr);
                        reqeustProcess.sendAddMeRequest(this.peerName,
                                listeningService.portNum,
                                SendingService.getSendingService().sendingPort,
                                InetAddress.getLocalHost(), newnbr.listPort,
                                newnbr.ip);
                        break;
                    case 6:
                        System.out.println("Degree of Node: " + Peer.neighboursList.size());
                        break;
                    case 7:
                        Utils.showAnalysisSubMenu();
                        int c = Utils.getInteger();
                        if (c == 0) {
                            reqeustProcess.sendAnalysisDegreeMessage(Peer.peerName, REGISTER_IP, REGISTER_PORT);
                        } else if (c == 1) {
                            reqeustProcess.sendAnalysisDiaMessage(Peer.peerName, REGISTER_IP, REGISTER_PORT);
                        } else {
                            System.out.println("Invalid choice ..! Aborting degree!");
                        }
                        break;
                    case 8:
                        Message msg = new Message();
                        msg.id = Utils.getUniqueId();
                        Peer.messageList.add(msg);
                        reqeustProcess.sendBroadcastInfoMessage(Peer.peerName, ListeningService.portNum, ListeningService.ip, msg);
                        break;
                    default:
                        Utils.showMenu(peerName);
                        break;
                }
            } catch (NumberFormatException nfe) {
                Utils.showMenu(peerName);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
